Type TWorld
	Global Worlds:TList = New TList
	Global Debug:Byte = True
	Global DebugCallbackSet:Byte = False
	
	Field dt:Float = 0.016
	Field irrMultiplier:Float = 32.0
	Field gravity:Float[] = [0.0,-9.81,0.0]
	'World Data
	Field World:Byte Ptr
	Field BodyList:TList = New TList
	Field MaterialMap:TMap = New TMap
	Field parent:TIrrlicht
	'Callbacks
	Field Standard_Transform_Callback(body:Byte Ptr,mat:Float Ptr,index:Int)
	Field Standard_ForceAndTorque_Callback(body:Byte Ptr,Mat:Float,index:Int)
	Field Standard_Activation_Callback(body:Byte Ptr)
	Field Contact_Begin_CallBack:Int(material:Byte Ptr,body0:Byte Ptr, body1:Byte Ptr)
	Field Contact_Process_CallBack:Int(material:Byte Ptr,body0:Byte Ptr, body1:Byte Ptr,timestep:Float)
	Field Contact_End_Callback(material:Byte Ptr , body0:Byte Ptr , body1:Byte Ptr) 
	
	'Profilers 
	'Field Profiler:TProfiler[20]
	
	'World AABB
	Field AABB:TVector[2]
	Field accumulator:Float
	Field lastupdate:Int = MilliSecs()
	Field updates:Int
	
	Field PlayState:Int = True
	
	
	Function DebugDrawGlobal:Object(irr:TIrrlicht)
		If Debug = False Then Return Null
		For Local W:TWorld = EachIn Worlds
			W.DebugDraw()
		Next
	End Function
	
	Function UpdateWorlds()
		For Local W:TWorld = EachIn Worlds
			W.AccuUpdate()
		Next
	End Function

	
	Function Create:TWorld(	irr:TIrrlicht, ..
								x1:Float = -1000.0, ..
								y1:Float = -100000.0, ..
								z1:Float = -1000.0, ..
								x2:Float = 1000.0, ..
								y2:Float = 100000.0, ..
								z2:Float = 1000.0)
		Local P:TWorld = New TWorld
		P.World = NewtonCreate(GetMemory  , FreeMemory)
		Local architecture:Int = 0
		?win32
			architecture = 1
		?
		NewtonSetPlatformArchitecture (P.World , architecture)  
		Local p1:Float[] = [x1,y1,z1]
		Local p2:Float[] = [x2,y2,z2]
		P.AABB[0] = New TVector
		P.AABB[1] = New TVector
		P.AABB[0].Set(x1,y1,z1)
		P.AABB[1].Set(x2,y2,z2)
		NewtonSetWorldSize(P.World ,p1 ,p2)
		'NewtonSetPerformanceClock (P.World , PhysicTimer)
		NewtonSetMultiThreadSolverOnSingleIsland(P.World,1)
		P.Parent = irr
		P.SetupCallbacks()
		Worlds.Addlast(P)
		Return P
	End Function
	
	Method SetupCallbacks()
		 Standard_Transform_Callback = TransformCallback
		 Standard_ForceAndTorque_Callback = ForceCallback
		
		'Irrlicht Debug Callbacks
		If DebugCallbackSet = False Then
			parent.AddCallback(TWorld.DebugDrawGlobal,CALLBACK_AFTERRENDER)
			DebugCallbackSet = False
		End If
	End Method
	
	Method ResizeWorld(x1:Float,y1:Float,z1:Float , x2:Float,y2:Float,z2:Float)
		Local p1:Float[] = [x1,y1,z1]
		Local p2:Float[] = [x2,y2,z2]
		AABB[0].Set(x1,y1,z1)
		AABB[1].Set(x2,y2,z2)
		NewtonSetWorldSize(World , p1 , p2)
	End Method
	
	Method SetPhysicModel(SolverModel:Int,FrictionModel:Int)
		NewtonSetSolverModel(World,SolverModel)
		NewtonSetFrictionModel(World,FrictionModel)
	End Method

	Method Update(UpTime:Float = - 1.0) 
		
		Local Time:Int = MilliSecs()
		GCSuspend()
		If  Uptime < 0 Then
			NewtonUpdate(World , GetDelta() ) 
		Else
			NewtonUpdate(World , Uptime ) 
		EndIf
		GCResume()
	End Method
	
	Method AccuUpdate()
		If PlayState = False Then Return
		
		accumulator:+ Min(MilliSecs() - lastupdate,60)/1000.0
		lastupdate = MilliSecs() 
		
		updates:Int = 0
		While accumulator >= dt
			Update(dt) 
			accumulator:- dt
			updates:+1
		Wend
		
	End Method
	
	Method GetUpdates:Int()
		Return updates
	End Method
	
		
	Method SetThreadCount:Int(Count:Int)
		NewtonSetThreadsCount(World,Count)
		Return NewtonGetThreadsCount(World) 
	End Method
	
	Method AddPhysicBody(Body:TBody)
		NewtonBodySetTransformCallback(Body.Node,Standard_Transform_Callback)
		NewtonBodySetForceAndTorqueCallback(Body.Node , Standard_ForceAndTorque_Callback) 
		BodyList.Addlast(Body) 
	End Method
	
	Method DebugDraw()
			If Debug = False Then Return
			Local mat:Matrix4= Matrix4.Create()
			mat.makeIdentity()
			Local material:SMaterial = SMaterial.Create()
			material.SetLighting(False)
			'Print "ZBuffer : " + material.getZBuffer()
			'material.setZBuffer(0)
			TIrrlicht.irr_Video.SetMaterial(material)
			TIrrlicht.irr_video.SetTransform(ETS_WORLD,mat)
			Local pp1:Float[] = [AABB[0].x,AABB[0].y,AABB[0].z]
			Local pp2:Float[] = [AABB[1].x,AABB[1].y,AABB[1].z]
			NewtonWorldForEachBodyInAABBDo(World,pp1,pp2,RenderBodyCollision)
	End Method	
	
	Method DestroyBody(Body:TBody)
		If Body <> Null Then
			NewtonDestroyBody(World , Body.node) 
			BodyList.Remove(Body)
		EndIf
	End Method
	
	Method SetSpeed(multiply:Float = 1.0) 
		dt = 1.0 / (60 * multiply)
	End Method
	
	Method Play()
		PlayState = True
	End Method
	
	Method Stop()
		PlayState = False
	End Method
	
	Method SetIrrlichtMultiplier(mult:Float = 32.0)
		irrMultiplier = mult
	End Method
	
	Function DebugMode(state:Byte = False)
		TWorld.Debug = state
	End Function 
	
	Method SetGravity(x:Float = 0,y:Float = -9.81,z:Float = 0)
		gravity = [x,y,z]
	End Method
	
End Type

